﻿using System.Linq;
using Enyim.Caching;
using SilenthinkCommon.Extension;
using Web.Controllers;
using Web.Components;
using SilenthinkContract;
using SilenthinkContract.Domain;

namespace Web.Areas.Cart.Controllers
{
    public abstract class CartBaseController : BaseController
    {
        protected const string CartSessionKey = "shoppingcart";


        protected CartBaseController(ILogService logService, IBaseService baseService, IExtraService extraService, IStoreService storeService, IOrderService orderService, IGameService gameService, IAuctionService auctionService, IPassportService passportService, IPaymentService paymentService, IMemcachedClient memcachedClient) : base(logService, baseService, extraService, storeService, orderService, gameService, auctionService, passportService, paymentService, memcachedClient)
        {
        }

        protected void ProcessDiscount(ShoppingCart cart)
        {
            var userId = cart.Identity.SkIdentity().Id;
            var discounts = StoreService.GetAvailableDiscount();
            foreach (var discount in discounts)
            {
                if (!ValidateDiscount(userId, discount)) continue;
                var discountRequirements = discount.DiscountRequirements;
                if (discountRequirements != null && discountRequirements.Any())
                {
                    var flag = discountRequirements.All(requirement => ValidateDiscountRequirement(userId, requirement, cart));
                    if (flag)
                    {
                        AssignDiscount(cart, discount);
                    }
                }
                else
                {
                    AssignDiscount(cart, discount);
                }
            }
        }
        #region ValidateDiscount
        private bool ValidateDiscount(long userId, Discount discount)
        {

            return discount.Limitation == DiscountLimitation.Unlimited || ValidateDiscount(userId, discount.Id, discount.Limitation, discount.LimitationTimes);
        }

        /// <summary>
        /// 验证折扣是否满足特定条件
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="discountId"></param>
        /// <param name="limitation"></param>
        /// <param name="limitationTimes"></param>
        /// <returns></returns>
        private bool ValidateDiscount(long userId, int discountId, DiscountLimitation limitation, int limitationTimes)
        {
            switch (limitation)
            {
                case DiscountLimitation.Unlimited:
                    return true;
                case DiscountLimitation.NTimesOnly:
                    return ValidateDiscount(discountId, limitationTimes);
                case DiscountLimitation.NTimesPerCustomer:
                    return ValidateDiscount(discountId, limitationTimes, userId);
            }
            return false;
        }

        private bool ValidateDiscount(int dicountId, int limitationTimes, long? userId = null)
        {
            return StoreService.ValidateDiscount(dicountId, limitationTimes, userId);
        }
        #endregion

        #region DiscountRequirement

        private static bool ValidateDiscountRequirement(long userId, DiscountRequirement discountRequirement, ShoppingCart cart)
        {
            switch (discountRequirement.RequirementRule)
            {
                case DiscountRequirementRule.HadSpentAmount:
                    return ValidateDiscountRequirement(userId, discountRequirement.SpentAmount);
                case DiscountRequirementRule.HasOneProduct:
                    return cart.Items.Any(o => discountRequirement.ProductVariantGuids.Contains(o.VariantId));
                case DiscountRequirementRule.HasAllProducts:
                    return cart.Items.All(o => discountRequirement.ProductVariantGuids.Contains(o.VariantId));

            }
            return false;
        }

        private static bool ValidateDiscountRequirement(long userId, decimal? amount)
        {
            var result = true;
            return result;
        }
        private static void AssignDiscount(ShoppingCart cart, Discount discount)
        {
            var cartItems = cart.Items;
            foreach (var item in cartItems)
            {
                if (discount.AssignedTo == DiscountAssignedTo.Category &&
                    discount.AppliedToCategories.Contains(item.CategoryCode))
                {
                    item.Discounts[discount.Id] = discount.GetDiscountAmount(item.UnitPrice);
                }
                if (discount.AssignedTo == DiscountAssignedTo.Productvariant &&
                    discount.AppliedToProductVariants.Contains(item.VariantId))
                {
                    item.Discounts[discount.Id] = discount.GetDiscountAmount(item.UnitPrice);
                }
                if (discount.AssignedTo == DiscountAssignedTo.OrderSubTotal)
                {
                    cart.OrderSubTotalDiscounts[discount.Id] = discount.GetDiscountAmount(item.UnitPrice);
                }
                if (discount.AssignedTo == DiscountAssignedTo.OrderTotal)
                {
                    cart.OrderTotalDiscounts[discount.Id] = discount.GetDiscountAmount(item.UnitPrice);
                }
                if (discount.AssignedTo == DiscountAssignedTo.Shipping)
                {
                    cart.ShippingDiscounts[discount.Id] = discount.GetDiscountAmount(item.UnitPrice);
                }
            }
        }

        #endregion
    }
}
